package models;

import play.mvc.*;
import play.libs.*;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import adapter.GameThread;
import akka.actor.*;
import static akka.pattern.Patterns.ask;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.util.*;

import models.msgs.*;
import models.msgs.Number;
import models.msgs.Result;
import static java.util.concurrent.TimeUnit.*;

public class Table extends UntypedActor {
    
    // Default table.
    static ActorRef defaultTable = Akka.system().actorOf(Props.create(Table.class));
    
    // Members of this table.
    static Map<String, ActorRef> members = new HashMap<String, ActorRef>();
    // Members of this table.
    static Map<String, String> idmembers = new HashMap<String, String>();
    static Map<String, String> antyidmembers = new HashMap<String, String>();
    // Members Socket
    static Map<String, GameThread> gameThreads = new HashMap<String, GameThread>();
       
    public static void join(final String name, WebSocket.In<JsonNode> in, WebSocket.Out<JsonNode> out ) throws Exception{

        // Send the Join message to the table
        String result = (String)Await.result(ask(defaultTable,new Join(name), 1000), Duration.create(1, SECONDS));
                
        if("OK".equals(result)) {
        	
            ActorRef player =  Akka.system().actorOf(
                    Props.create(Human.class, name, in, out,  defaultTable ));
            
            GameThread polaczenie = new GameThread(player, defaultTable, name);
            polaczenie.ConnectToServer("127.0.0.1", "4444");
            
            gameThreads.put(name, polaczenie);
            members.put(name, player);            
            String text =  "my Actor has been added to Table"; 
            notifyAll(new Info(text,name));                             
        }
    }
    
    public static void quit(final String username) throws Exception{

        //to do
    }
    
       
    public void onReceive(Object message) throws Exception {
        
        if(message instanceof Join) {
            
            Join join = (Join) message;
                        
            if(false){
            	// if username is already taken do sth        	
            }
            else {                
                getSender().tell("OK", getSelf());
            }
        } else if (message instanceof Task)
        {   
        	String task = ((Task) message).getTask();
        	String name = ((Task) message).getName();  
        	//notifyAll(new Info(task,"Table"));
        	GameThread tmp = (GameThread)gameThreads.get(name);
        	tmp.send(task);
        }
        else if (message instanceof Result)
        {   
        	String result = ((Result) message).getResult();
        	String name = ((Result) message).getName();  
        	//notifyAll(new Info(result,"Result"));
            if(name.equals("CARDS"))
              getSender().tell(new EventMsg("CARDS",result), defaultTable);
            if(name.equals("NEWROUND"))
              getSender().tell(new EventMsg("NEWROUND","Table"), defaultTable);
            else if(name.equals("WYMIANA"))
              getSender().tell(new EventMsg("WYMIANA","Table"), defaultTable);
            
        	getSender().tell(new Info(result,"Table"), defaultTable);
        }
        else if (message instanceof LicytacjaMsg)
        {   
        	String id = ((LicytacjaMsg) message).getId();
        	String msg = ((LicytacjaMsg) message).getMsg();
        	String gracz = idmembers.get(id);
        	if(gracz!=null) {
        	  getSender().tell(new Info("Gracz Licytujac: "+gracz+" "+msg, "Table"),defaultTable);
        	}
        	else
        	  getSender().tell(new Info("Bot Licytujac: BOT"+id+" "+msg, "Table"),defaultTable);
        	
        	notifyAll(new EventMsg("BID", gracz));
        }
        else if (message instanceof IDGracza) {   
        	String id = ((IDGracza) message).getId();
        	String name = ((IDGracza) message).getName();
        	idmembers.put(id, name);
        	antyidmembers.put(name, id);
        	
        	getSender().tell((IDGracza)message, defaultTable);
        }
        else if (message instanceof DeckMsg) {   
        	String id = ((DeckMsg) message).getId();
        	String cards = ((DeckMsg) message).getCards();
        	String task = ((DeckMsg) message).getTask();
        	String gracz=idmembers.get(id);
        	if(gracz!=null)
        	  getSender().tell(new Info(cards,gracz), defaultTable);
        	else {
        	  if(id.startsWith("B"))
        	    getSender().tell(new Info(cards,"BOT"+id.substring(1)), defaultTable);
        	  else if(id.startsWith("FB"))
        		getSender().tell(new Info("Zrezygnowa","BOT"+id.substring(2)), defaultTable);
        	  else if(id.startsWith("F"))
          		getSender().tell(new Info("Zrezygnowa",idmembers.get(id.substring(1))), defaultTable);
        	  else if(id.equals("Remis"))
        		  getSender().tell(new Info("Remis","Table"), defaultTable);
        	  else
        		getSender().tell(new Info(cards,"Player"+id.substring(1)), defaultTable);
        	}
        	
        	if(task.equals("CASH")) {
        	  getSender().tell(new EventMsg("ALL","Table"), defaultTable);
        	}
        	
        	else if(task.equals("BALL")) {
          	  getSender().tell(new EventMsg("BALL","Table"), defaultTable);
          	}
        }
        else if (message instanceof SpecialMsg) {   
          String id = ((SpecialMsg) message).getId();
          String msg = ((SpecialMsg) message).getMsg();
          String task = ((SpecialMsg) message).getTask();
          String gracz=idmembers.get(id);
          
          if(task.equals("ALLIN")) {
            if(members.get(gracz).equals(getSender()))
              getSender().tell(new EventMsg("CREATE","Table"), defaultTable);
            else
              getSender().tell(new EventMsg("ALLIN","Table"), defaultTable);
          }
          
          getSender().tell(new Info(msg,gracz), getSelf());
        }
        else if (message instanceof RankingMsg)
        {   
          String[][] id = ((RankingMsg) message).getId();
          String[] idWiner = ((RankingMsg) message).getWiner();
          int[][] money = ((RankingMsg) message).getMoney();
          int[] runda = ((RankingMsg) message).getRunda();
          
          String msg="<br />";
          
          //G_RANKING_2_1_[0;1;0,60;1,140;]
          
          for(int i=0; i<id.length;i++) {
        	if(idWiner[i].startsWith("B"))
              msg+="Runda: "+runda[i]+" Zwyciezyl: "+"BOT"+idWiner[i].substring(1);
        	else
        	  msg+="Runda: "+runda[i]+" Zwyciezyl: "+idmembers.get(idWiner[i]);
        	
            for(int j=0;j<id[i].length;j++) {
          	  if(id[i][j].startsWith("B"))
                msg+=" &nbsp &nbsp &nbsp"+"BOT"+id[i][j].substring(1)+": "+money[i][j];
        	  else
        	    msg+=" &nbsp &nbsp &nbsp"+idmembers.get(id[i][j])+": "+money[i][j];
            }
            
            msg+="<br />";
          }
            		
          getSender().tell(new Info(msg,"Table"), getSelf());
        }
        else if (message instanceof Info)
        {   
        	String text = ((Info) message).getText();
        	String name = ((Info) message).getName();  
        	
        	notifyAll(new Info(text, name));
        }  
        else if(message instanceof Quit)  {            
           
            String name = ((Quit)message).getName();            
            members.remove(name);
            gameThreads.remove(name);
            idmembers.remove(antyidmembers.get(name));
            antyidmembers.remove(name);
            String text = "has left the game";            		
            notifyAll(new Info(text, name));
          
        
        } else {
            unhandled(message);
        }
        
    }
    
        
    static public void notifyAll(Object msg)
    {
        for (ActorRef member : members.values())
        {
            member.tell(msg, defaultTable);
        }
    }
        
}

